package com.mol.market.ui_v4;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import com.actionbarsherlock.app.SherlockFragment;
import com.mol.market.Constants;
import com.mol.market.R;
import com.mol.market.Session;
import com.mol.market.common.download.DownloadManager;
import com.mol.market.common.network.ApiResponse;
import com.mol.market.common.network.MarketAPI;
import com.mol.market.common.util.DBUtils;
import com.mol.market.common.util.DialogUtil;
import com.mol.market.common.util.ImageUtils;
import com.mol.market.common.util.Utils;
import com.mol.market.common.vo.DownloadInfo;
import com.mol.market.common.vo.DownloadItem;
import com.mol.market.common.vo.ProductDetail;
import com.mol.market.common.widget.FragmentTabHostImpl;
import com.mol.market.ui.LoginActivity;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 产品详细页（包括产品详细信息和评论信息，使用Tab）。
 *
 * Author: Andrew.Wang
 * Date  : 13-1-8
 */
public class ProductFragment extends SherlockFragment implements
        LoaderManager.LoaderCallbacks<ApiResponse>, View.OnClickListener, Observer {

    private ProductDetail mProductDetail;
    private DownloadInfo mDownloadInfo;
    private ProductDetailActivity mActivity;
    private boolean mIsMultiPanel;
    private Session mSession;
    private View mControlDownload;
    private View mDownloadBar;
    private ViewPager mViewPager;
    private TabsAdapter mTabsAdapter;
    private FragmentTabHostImpl mTabHost;
    private RadioGroup mFakeTabHost;

    /** 应用的初始状态 */
    private int mInitStatus;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(false);
        mActivity = (ProductDetailActivity) getSherlockActivity();
        mSession = Session.get(mActivity);
        mSession.addObserver(this);
        mProductDetail = (ProductDetail) getArguments().getSerializable(
                Constants.EXTRA_PRDUCT_DETAIL);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_product, container, false);

        // 初始化Tab（产品详细和评论）
        // 注意，由于存在Fragment套Fragment的使用场景，所以使用了getChildFragmentManager
        mTabHost = (FragmentTabHostImpl) v.findViewById(android.R.id.tabhost);
        mFakeTabHost = (RadioGroup) v.findViewById(R.id.fake_tab_widget);

        mViewPager = (ViewPager) v.findViewById(R.id.pager);
        View rootView;

        if (mTabHost == null) {

            mIsMultiPanel = true;
            rootView = mFakeTabHost;

            mTabsAdapter = new TabsAdapter(this, mViewPager, rootView);

            mTabsAdapter.addTab("detail",
                    ProductDetailFragment.class, getArguments());
            mTabsAdapter.addTab("comments",
                    ProductCommentsFragment.class, getArguments());

        } else {

            mIsMultiPanel = false;
            rootView = mTabHost;
            mTabHost.setup(mActivity, getFragmentManager(), R.id.real_content);
            mTabHost.getTabWidget();

            TextView detailTab = (TextView)
                    mActivity.getLayoutInflater().inflate(R.layout.tab_indicator, null);
            detailTab.setText(R.string.label_details);

            TextView commentTab = (TextView)
                    mActivity.getLayoutInflater().inflate(R.layout.tab_indicator, null);
            commentTab.setText(R.string.comment_lab);

            mTabsAdapter = new TabsAdapter(this, mViewPager, rootView);

            mTabsAdapter.addTab(mTabHost.newTabSpec("detail").setIndicator(detailTab),
                    ProductDetailFragment.class, getArguments());
            mTabsAdapter.addTab(mTabHost.newTabSpec("comments").setIndicator(commentTab),
                    ProductCommentsFragment.class, getArguments());
        }

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // 初始化产品信息
        initProductInfo(mProductDetail);

        initAppStatus(mProductDetail);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mSession.deleteObserver(this);
        mTabHost = null;
        mFakeTabHost = null;
        mTabsAdapter = null;
        mViewPager = null;
        mSession = null;
        mProductDetail = null;
        mActivity = null;
        mDownloadInfo = null;
        mControlDownload = null;
        mDownloadBar = null;
    }

    /**
     * 初始化产品的详细信息（开发者,评星）
     */
    private void initProductInfo(ProductDetail product) {
        
        ImageView ivIcon = (ImageView) mActivity.findViewById(R.id.icon);
        ImageUtils.download(mActivity, product.getIconUrl(), ivIcon,
                R.drawable.loading_icon, true, false);

        RatingBar rating = (RatingBar) mActivity.findViewById(R.id.rating);
        rating.setRating(product.getRating());

        TextView ratingNum = (TextView) mActivity.findViewById(R.id.rating_num);
        ratingNum.setText(getString(R.string.label_comments, product.getRatingCount()));

        mActionButton = (TextView) mActivity.findViewById(R.id.info_action_1);
        mActionButton.setOnClickListener(this);

        if (mIsMultiPanel) {
            mControlDownload = mActivity.findViewById(R.id.info_action_1);
        } else {
            mControlDownload = mActivity.findViewById(R.id.control_download);
        }
        mDownloadBar = mActivity.findViewById(R.id.download_bar);
        ImageButton cancel = (ImageButton) mDownloadBar.findViewById(R.id.cancel);
        ImageButton pause = (ImageButton) mDownloadBar.findViewById(R.id.pause);
        cancel.setOnClickListener(this);
        pause.setOnClickListener(this);

        mProgressBar = (ProgressBar) mActivity.findViewById(R.id.progress);
        mStatusInfo = (TextView) mActivity.findViewById(R.id.status_info);
        mStatusIcon = (ImageView) mActivity.findViewById(R.id.action);
    }

    /** 下载进度条 */
    private ProgressBar mProgressBar;
    /** 应用状态指示信息 */
    private TextView mStatusInfo;
    /** 应用状态指示图标 */
    private ImageView mStatusIcon;
    /** 应用操作按钮 */
    private TextView mActionButton;

    /** 应用当前状态 */
    private int mCurrentStatus;

    // -----------------------------------------
    // -------------应用状态机-------------------
    // -----------------------------------------
    /** 正常状态（未下载） */
    private static final int STATUS_NORMAL = 0;
    /** 已安装 */
    private static final int STATUS_INSTALLED = 1;
    /** 可更新 */
    private static final int STATUS_UPDATE = 2;
    /** 已下载，未安装 */
    private static final int STATUS_DOWNLOADED = 3;
    /** 已下载，未安装（可更新应用） */
    private static final int STATUS_UPDATE_DOWNLOADED = 4;
    /** 下载中 */
    private static final int STATUS_DOWNLOADING = 5;
    /** 下载错误 */
    private static final int STATUS_ERROR = 6;
    /** 下载暂停 */
    private static final int STATUS_PAUSED = 7;

    /*
    * 刷新应用的下载进度
    */
    private void refreshDownloadingStatus(DownloadInfo info) {

        synchronized (this) {
            mDownloadInfo = info;
        }
        if (info == null) {
            return;
        }

        final int currentStatus = info.mStatus;

        if (DownloadManager.Impl.isStatusNotCancelError(currentStatus)) {
            // 下载失败
            mCurrentStatus = STATUS_ERROR;
            mStatusIcon.setImageResource(R.drawable.action_resume);
            mStatusInfo.setText(R.string.download_error);

        } else if (DownloadManager.Impl.isStatusPaused(currentStatus)) {

            // 下载暂停中
            mCurrentStatus = STATUS_PAUSED;
            mProgressBar.setIndeterminate(true);
            mStatusIcon.setImageResource(R.drawable.action_resume);
            mStatusInfo.setText(R.string.download_paused);

        } else if (DownloadManager.Impl.isStatusPending(currentStatus)) {

            // 网络连接中
            mCurrentStatus = STATUS_DOWNLOADING;
            mStatusIcon.setImageResource(R.drawable.action_pause);
            mStatusInfo.setText(R.string.download_try);
            mProgressBar.setIndeterminate(true);

        } else if (DownloadManager.Impl.isStatusRunning(currentStatus)) {

            // 下载中状态
            mCurrentStatus = STATUS_DOWNLOADING;
            mStatusIcon.setImageResource(R.drawable.action_pause);
            mProgressBar.setIndeterminate(false);
            mProgressBar.setProgress(info.mProgressNumber);
            String remainText = Utils.calculateRemainBytes(mActivity, info.mCurrentSize, info.mTotalSize);

            if (mIsMultiPanel) {

                mStatusInfo.setText(mActivity.getString(R.string.download_status_downloading, info.mProgress));

            } else {
                if (TextUtils.isEmpty(remainText)) {
                    mStatusInfo.setText(
                            mActivity.getString(R.string.download_status_downloading, info.mProgress));
                } else {
                    mStatusInfo.setText(
                            mActivity.getString(R.string.download_status_downloading, info.mProgress) +
                                    "，" +  remainText);
                }
            }

        } else if (DownloadManager.Impl.isStatusSuccess(currentStatus)) {

            // 下载成功
            if (mInitStatus == STATUS_UPDATE) {
                mCurrentStatus = STATUS_UPDATE_DOWNLOADED;
            } else {
                mCurrentStatus = STATUS_DOWNLOADED;
            }
            mProductDetail.setFilePath(info.mFilePath);
            mStatusInfo.setText(R.string.notification_download_complete);
            mActionButton.setText(R.string.label_install);

        } else if (currentStatus == DownloadManager.Impl.STATUS_INSTALLED) {

            // 安装完成
            mCurrentStatus = STATUS_INSTALLED;
            mActionButton.setText(R.string.label_open);

        } else {
            // 下载失败
            mCurrentStatus = mInitStatus;
            mProgressBar.setProgress(0);
        }
        switchAppStatus(mCurrentStatus);
    }

    /**
     * 切换下载控制条状态
     */
    private void switchAppStatus(int status) {

        switch (status) {

            case STATUS_DOWNLOADING:
            case STATUS_ERROR:
            case STATUS_PAUSED:{
                mControlDownload.setVisibility(View.INVISIBLE);
                mDownloadBar.setVisibility(View.VISIBLE);
                break;
            }
            case STATUS_NORMAL:
            case STATUS_INSTALLED:
            case STATUS_UPDATE:
            case STATUS_DOWNLOADED:
            case STATUS_UPDATE_DOWNLOADED:
            default:{
                mControlDownload.setVisibility(View.VISIBLE);
                mDownloadBar.setVisibility(View.INVISIBLE);
                break;
            }
        }
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.info_action_1: {

                handleAction(mCurrentStatus);
                switchAppStatus(mCurrentStatus);
                break;
            }

            case R.id.cancel: {
                mSession.getDownloadManager().cancelDownload(mDownloadInfo.id);
                mSession.removeStarted(mDownloadInfo.mPackageName);
                mProductDetail.isPendingDownload = false;
                break;
            }

            case R.id.pause: {

                if (mCurrentStatus == STATUS_PAUSED) {
                    // 马上下载
                    DownloadInfo info = mSession.getDownloadingList().get(
                            mProductDetail.getPackageName());
                    if (info != null) {
                        mSession.getDownloadManager().resumeDownload(info.id);
                    }
                } else {
                    // 暂停下载
                    mSession.getDownloadManager().pauseDownload(mDownloadInfo.id);
                    mSession.removeStarted(mDownloadInfo.mPackageName);
                    mProductDetail.isPendingDownload = true;
                }
                break;
            }
        }
    }

    /*
     * 处理ActionBar按钮的动作
     */
    private void handleAction(int status) {

        switch (status) {

            case STATUS_NORMAL:
            case STATUS_UPDATE:

                // 开始下载
                download();
                Utils.trackEvent(mActivity, Constants.GROUP_8,
                        Constants.DETAIL_DOWNLOAD);
                break;

            case STATUS_INSTALLED:

                // 打开此应用
                Utils.openApk(mActivity, mProductDetail.getPackageName());
                Utils.trackEvent(mActivity, Constants.GROUP_8,
                        Constants.DETAIL_OPEN);
                break;

            case STATUS_DOWNLOADED:
            case STATUS_UPDATE_DOWNLOADED:

                // 开始安装
                executeInstallation();
                Utils.trackEvent(mActivity, Constants.GROUP_8,
                        Constants.DETAIL_INSTALL);
                break;

            default:
                break;
        }
    }

    /*
     * 安装前检查签名一致性
     */
    private void executeInstallation() {
        // 下载完成
        if (Utils.compareFileWithPathAndPkg(mActivity, mProductDetail.getFilePath(),
                mProductDetail.getPackageName())) {
            Utils.installApk(mActivity, new File(mProductDetail.getFilePath()));
            return;
        }

        DialogUtil.createComfirmDownloadDialog(mActivity, false, new DialogUtil.WarningDialogListener() {

            @Override
            public void onWarningDialogOK(int id) {
                mSession.mNotSameApps.put(mProductDetail.getPackageName(), mProductDetail.getFilePath());
                Utils.uninstallApk(mActivity, mProductDetail.getPackageName());
            }

            @Override
            public void onWarningDialogCancel(int id) {
            }
        }).show();
    }

    /**
     * 初始化App初始状态
     */
    private void initAppStatus(ProductDetail product) {

        if (mSession.getUpdateList().containsKey(mProductDetail.getPackageName())) {
            mInitStatus = STATUS_UPDATE;
        } else if (mSession.getInstalledApps().contains(mProductDetail.getPackageName())) {

            HashMap<String, Object> obj = mSession.mPreloadInstalled.get(mProductDetail.getPackageName());
            //fix bug by Chaos at 2013/3/18
            //修复“列表下载应用->安装完应用->点击应用进入详情页”崩溃的bug
            if (obj != null && obj.get(Constants.KEY_PRODUCT_VERSION_CODE) != null) {
                int versionCode = (Integer) obj.get(Constants.KEY_PRODUCT_VERSION_CODE);
                if (mProductDetail.getVersionCode() > versionCode) {
                    mInitStatus = STATUS_UPDATE;
                } else {
                    mInitStatus = STATUS_INSTALLED;
                }
            } else {
                mInitStatus = STATUS_INSTALLED;
            }

        } else {
            mInitStatus = STATUS_NORMAL;
        }

        if (mInitStatus == STATUS_UPDATE) {
            mActionButton.setText(R.string.label_update);
        } else if (mInitStatus == STATUS_DOWNLOADED) {
            mActionButton.setText(R.string.label_install);
        } else if (mInitStatus == STATUS_INSTALLED) {
            mActionButton.setText(R.string.label_open);
        } else {
            mActionButton.setText(R.string.label_download);
        }

        ConcurrentHashMap<String, DownloadInfo> list = mSession.getDownloadingList();

        if (list != null) {

            DownloadInfo info = list.get(product.getPackageName());
            if (info == null) {
                mCurrentStatus = mInitStatus;
                switchAppStatus(mCurrentStatus);
                return;
            }

            mDownloadInfo = info;
            refreshDownloadingStatus(mDownloadInfo);
        }
    }

    /**
     * 开始下载任务
     */
    public void download() {

        if (Constants.PAY_TYPE_PAID == mProductDetail.getPayCategory()) {

            if (!mSession.isLogin()) {
                // 收费应用必须登录
                Intent loginIntent = new Intent(mActivity, LoginActivity.class);
                startActivity(loginIntent);
                return;
            }

            DBUtils.isBought(mActivity, mProductDetail.getPid(),
                    new DBUtils.DbOperationResultListener<Boolean>() {
                        @Override
                        protected void onQueryResult(Boolean result) {
                            if (!result && isVisible()) {
                                mActivity.showDialog(ProductDetailActivity.DIALOG_PURCHASE);
                            } else {
                                executeDownload();
                            }
                        }
                    });
        } else {
            // 免费应用
            executeDownload();
        }
    }

    /**
     * 根据下载状态进行下载处理
     */
    private void executeDownload() {

        ConcurrentHashMap<String, DownloadInfo> list = mSession.getDownloadingList();

        DownloadInfo info = list.get(mProductDetail.getPackageName());
        boolean isAlreadyInTask = (info != null) && Utils.isFileExist(info.mFilePath);
        if (isAlreadyInTask) {
            // 下载中
            Utils.makeEventToast(mActivity, getString(R.string.warning_comment_later), false);
            return;
        }

        if (mSession.getInstalledApps().contains(mProductDetail.getPackageName())) {
            // 升级签名检查
            if (!Utils.isSameSign(mActivity, mProductDetail.getPackageName(),
                    mProductDetail.getRsaMd5())) {

                    DialogUtil.createComfirmDownloadDialog(mActivity, true,
                            new DialogUtil.WarningDialogListener() {

                                @Override
                                public void onWarningDialogOK(int id) {
                                    // 开始下载
                                    if (mSession.addDownload(mProductDetail.getPackageName())) {
                                        getLoaderManager().initLoader(
                                                MarketAPI.ACTION_GET_DOWNLOAD_URL, null, ProductFragment.this);
                                    }
                                }

                                @Override
                                public void onWarningDialogCancel(int id) {
                                }

                            }).show();
                return;
            }
        }
        // 开始下载
        if (mSession.addDownload(mProductDetail.getPackageName())) {
            mActivity.getSupportLoaderManager().initLoader(
                    MarketAPI.ACTION_GET_DOWNLOAD_URL, null, this);
        }
    }

    /**
     * 开始下载任务
     */
    private void startDownload(DownloadItem info) {
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(info.url));
        request.setPackageName(mProductDetail.getPackageName());
        request.setTitle(mProductDetail.getName());
        request.setIconUrl(mProductDetail.getIconUrl());
        request.setMD5(info.fileMD5);
        request.setSourceType(com.mol.market.common.download.Constants.DOWNLOAD_FROM_MARKET);
        mSession.getDownloadManager().enqueue(mActivity, request, null);

//        if (mIsRecommend) {
//            // 首页推荐带来的直接下载量统计
//            Utils.trackEvent(mActivity, Constants.GROUP_8,
//                    String.format(Constants.DETAIL_RECOMMEND_APP, mProductDetail.getName()));
//        }
        Utils.makeEventToast(mActivity, getString(R.string.alert_start_download),
                false);

//        Intent i = getIntent();
//        String nid = i.getStringExtra(Constants.EXTRA_APP_NID);
//        String rule = i.getStringExtra(Constants.EXTRA_APP_RULE);
//        if (!TextUtils.isEmpty(nid)) {
//            MarketAPI.reportIftttResult(getApplicationContext(), mProduct.getPid(), nid, rule,
//                    Constants.REPORT_TYPE_DOWNLOAD);
//        }
    }

    @Override
    public Loader<ApiResponse> onCreateLoader(int id, Bundle args) {

        if (MarketAPI.ACTION_GET_DOWNLOAD_URL == id) {

            return MarketAPI.initGetDownloadInfoLoader(mActivity, mProductDetail.getPid(),
                    mProductDetail.getSourceType());
        }

        return null;
    }

    @Override
    public void onLoadFinished(Loader<ApiResponse> loader, ApiResponse data) {

        if (data.status == ApiResponse.STATUS_OK) {
            DownloadItem info = (DownloadItem) data.result;
            startDownload(info);
            return;
        }
    }

    @Override
    public void onLoaderReset(Loader<ApiResponse> loader) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void update(Observable observable, Object data) {
        if (data instanceof ConcurrentHashMap) {
            ConcurrentHashMap<String, DownloadInfo> mDownloadingTask =
                    (ConcurrentHashMap<String, DownloadInfo>) data;
            DownloadInfo info = mDownloadingTask.get(mProductDetail.getPackageName());

            if (info == null) {
                return;
            }
            refreshDownloadingStatus(info);
        }
    }

    /**
     * This is a helper class that implements the management of tabs and all
     * details of connecting a ViewPager with associated TabHost.  It relies on a
     * trick.  Normally a tab host has a simple API for supplying a View or
     * Intent that each tab will show.  This is not sufficient for switching
     * between pages.  So instead we make the content part of the tab host
     * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
     * view to show as the tab content.  It listens to changes in tabs, and takes
     * care of switch to the correct paged in the ViewPager whenever the selected
     * tab changes.
     */
    public static class TabsAdapter extends FragmentStatePagerAdapter
            implements ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener,
                        RadioGroup.OnCheckedChangeListener {
        private final Context mContext;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
        private FragmentTabHostImpl mTabHost;
        private RadioGroup mFakeTabHost;
        private boolean mIsMultiPanel;

        static final class TabInfo {
            private final Class<?> clss;
            private final Bundle args;
            private final String tag;
            private Fragment fragment;

            TabInfo(Class<?> _class, Bundle _args, String _tag) {
                clss = _class;
                args = _args;
                tag = _tag;
            }
        }

        public TabsAdapter(SherlockFragment fragment, ViewPager pager,
                View tabHost) {
            super(fragment.getFragmentManager());
            mContext = fragment.getSherlockActivity();

            if (tabHost instanceof FragmentTabHostImpl) {
                mTabHost = (FragmentTabHostImpl) tabHost;
                mIsMultiPanel = false;
            } else {
                mFakeTabHost = (RadioGroup) tabHost;
                mIsMultiPanel = true;
            }

            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }

        public void addTab(TabHost.TabSpec tab, Class<?> clss, Bundle args) {

            TabInfo info = new TabInfo(clss, args, tab.getTag());

            mTabHost.setOnTabChangedListener(this);
            mTabHost.addTab(tab, clss, args);
            mTabs.add(info);
            notifyDataSetChanged();
        }

        public void addTab(String tag, Class<?> clss, Bundle args) {

            TabInfo info = new TabInfo(clss, args, tag);

            mFakeTabHost.setOnCheckedChangeListener(this);
            mTabs.add(info);
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mTabs.size();
        }

        @Override
        public Fragment getItem(int position) {
            TabInfo info = mTabs.get(position);
            if (info.fragment == null) {
                info.fragment =
                        Fragment.instantiate(mContext, info.clss.getName(), info.args);
            }
            return info.fragment;
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {

            if (mIsMultiPanel) {
                int id = position == 0 ? R.id.rb_detail : R.id.rb_comment;
                mFakeTabHost.check(id);
            } else {
                mTabHost.setCurrentTab(position);
            }
        }

//        public void destroy() {
//            mTabs.clear();
//            notifyDataSetChanged();
//        }

        @Override
        public int getItemPosition(Object object){
            return PagerAdapter.POSITION_NONE;
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }

        @Override
        public void onTabChanged(String tabId) {

            for (int i = 0; i < mTabs.size(); i++) {
                if (tabId.equals(mTabs.get(i).tag)) {
                    mViewPager.setCurrentItem(i);
                }
            }
        }

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            if (checkedId == R.id.rb_detail) {
                mViewPager.setCurrentItem(0);
            } else if (checkedId == R.id.rb_comment) {
                mViewPager.setCurrentItem(1);
            }
        }

    }

}
